package cheme.ProcessModel.Cmds;

import cheme.ProcessModel.IParent;
import cheme.ProcessModel.ProcessUnits.ProcessUnit;
import cheme.ProcessModel.ProcessUnits.Streams.Stream;

public class CreateTerminalStreamCmd extends CreateStreamCmd
{
	protected IParent sourceParent = null;
	protected IParent sinkParent = null;

	public CreateTerminalStreamCmd(ProcessUnit source)
	{
		super(source);
		this.sourceParent = source.getParent();
	}
	
	public CreateTerminalStreamCmd(CreateTerminalStreamCmd src)
	{
		super(src); //copies the stream, source, sink over for me

		this.sourceParent = src.sourceParent;
		this.sinkParent = src.sinkParent;
	}
	
	public CreateTerminalStreamCmd(CreateStreamCmd src)
	{
		super(src);
	}
	
	public CreateTerminalStreamCmd(Stream stream, ProcessUnit source, IParent sourceParent)
	{
		super(source);
		
		this.stream = stream;
		this.source = source;
		this.sourceParent = sourceParent;
	}

	public void execute()
	{
		try
		{
			if(addSourceOnExecute())
			{
				sourceParent.add(source);
			}
			
			if(addSinkOnExecute())
			{
				sinkParent.add(sink);
			}
			
			super.execute();
			
//			stream.setSource(source);
//			stream.setSink(sink);
//
//			stream.attachSource();
//			stream.attachSink();
		}
		catch(Exception e)
		{
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
//	public void setStream(IStream stream)
//	{
//		this.stream = stream;
//	}
	
//	/**
//	 * Will instigate adding the specified source to the specified parent upon execution.
//	 * @param source
//	 * @param sourceParent
//	 */
//	public void setSource(IProcessUnit source, IParent sourceParent)
//	{
//		this.sourceParent = sourceParent;
//		setSource(source);
//	}
	
//	@Override
//	public void setSource(IProcessUnit source)
//	{
//		this.source = source;
//	}

	/**
	 * Will instigate adding the specified sink to the specified parent upon execution.
	 * @param source
	 * @param sourceParent
	 */
	public void setSink(ProcessUnit sink, IParent sinkParent)
	{
		this.sinkParent = sinkParent;
		setSink(sink);
	}

	@Override
	public void setSink(ProcessUnit sink)
	{
		this.sink = sink;
	}
	
	private boolean addSourceOnExecute()
	{
		return null != sourceParent;
	}
	
	private boolean addSinkOnExecute()
	{
		return null != sinkParent;
	}

	public void undo()
	{
		assert null != stream;

		if(addSourceOnExecute())
		{
			sourceParent.remove(source);
		}
		
		if(addSinkOnExecute())
		{
			sinkParent.remove(sink);
		}
		
		stream.detachSource();
		stream.detachSink();
	}
}
